package com.liwujie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liwujie.car.dto.ShopCartItemDTO;
import com.liwujie.car.feign.ShopCartFeignClient;
import com.liwujie.common.order.*;
import com.liwujie.core.bean.ResultBean;
import com.liwujie.core.controller.BaseController;
import com.liwujie.core.utils.DateUtils;
import com.liwujie.dto.OrderDTO;
import com.liwujie.feign.UserAddrFeignClient;
import com.liwujie.mapper.OrderAddrMapper;
import com.liwujie.mapper.OrderMapper;
import com.liwujie.model.Order;
import com.liwujie.model.OrderItem;
import com.liwujie.service.IOrderItemService;
import com.liwujie.service.IOrderService;
import com.liwujie.utils.OrderRedisUtil;
import com.liwujie.utils.SnowflakeIdWorker;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 订单信息 服务实现类
 * </p>
 *
 * @author liwujie
 * @since 2025-04-14
 */
@Service
@Log4j2
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {
    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private UserAddrFeignClient userAddrFeignClient;
    @Autowired
    private ShopCartFeignClient shopCartFeignClient;

    @Autowired
    private OrderRedisUtil orderRedisUtil;
    @Autowired
    private IOrderItemService orderItemService;

    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker; // 注入雪花ID生成器

    @Autowired
    private OrderAddrMapper orderAddrMapper;


    @Override
    public OrderConfirmVO confirmOrder(Long userId, OrderDTO orderDTO) {
        //订单确认信息
        OrderConfirmVO orderConfirmVO = new OrderConfirmVO();
        // 存入购物车ID（关键修改！）
        orderConfirmVO.setShopCartIds(orderDTO.getShopCartIds());
        // 存入其他前端参数（用于提交时校验
        orderConfirmVO.setRemarks(orderDTO.getRemarks());
        orderConfirmVO.setDeliveryType(orderDTO.getDeliveryType());
        orderConfirmVO.setPaymentType(orderDTO.getPaymentType());
       /* //1. 获取用户地址信息
        ResultBean<UserAddrVO> addResult = userAddrFeignClient.getUserAddrByAddrId(orderDTO.getOrderAddrId());
        if (addResult.isSuccess()) {
            orderConfirmVO.setUserAddr(addResult.getData());
        } else {
            throw new RuntimeException("获取用户地址信息失败");
        }*/
        // 1. 模拟用户地址信息
        UserAddrVO mockAddr = new UserAddrVO();
        mockAddr.setAddrId(orderDTO.getOrderAddrId());
        mockAddr.setConsignee("测试用户");
        mockAddr.setMobile("13800138000");
        mockAddr.setProvince("广东省");
        mockAddr.setCity("深圳市");
        mockAddr.setArea("南山区");
        mockAddr.setAddr("科技园路100号");
        mockAddr.setIsDefault(1);
        orderConfirmVO.setUserAddr(mockAddr);


        //获取购物车商品(区分购物车和直接购买)
        List<ShopCartItemVO> shopCartItems = getShopCartItems(userId, orderDTO);
        //3.按照店铺计算订单信息
        List<ShopOrderVO> shopOrders = calculateShopOrders(shopCartItems);
        orderConfirmVO.setShopOrders(shopOrders);
        //4.计算订单总金额
        long totalAmount = shopCartItems.stream().mapToLong(item -> item.getSkuPriceFee() * item.getCount()).sum();
        orderConfirmVO.setTotalAmount(totalAmount);
        orderConfirmVO.setFinalAmount(totalAmount);//简化处理无优惠券的情况

        //5 设置其他信息
        orderConfirmVO.setDeliveryType(orderDTO.getDeliveryType());
        orderConfirmVO.setPaymentType(orderDTO.getPaymentType());
        orderConfirmVO.setExpectDeliveryTime(orderDTO.getExpectDeliveryTime());
        orderConfirmVO.setTotalAmount((long) shopCartItems.stream().mapToInt(ShopCartItemVO::getCount).sum());
        //缓存订单确认信息
        orderRedisUtil.cacheOrderConfirm(userId, orderConfirmVO);
        return orderConfirmVO;
    }

    private List<ShopCartItemVO> getShopCartItems(Long userId, OrderDTO orderDTO) {
        //直接购买路径
        if (orderDTO.getShopCartItemDTO() != null) {
            ShopCartItemDTO directBuyItem = orderDTO.getShopCartItemDTO();
            ShopCartItemVO item = new ShopCartItemVO();
            item.setSkuId(directBuyItem.getSkuId());
            item.setSpuId(directBuyItem.getSpuId());
            item.setCount(directBuyItem.getCount());
            item.setShopId(directBuyItem.getShopId());
            // 这里需要调用商品服务获取商品详情（价格、名称等）

            // 模拟数据
            item.setSkuPriceFee(10000L); // 价格100元
            item.setSpuName("测试商品");
            item.setSkuName("测试规格");
            item.setImgUrl("https://example.com/product.jpg");
            return Collections.singletonList(item);
        }
        /*//购物车路径
        else if (orderDTO.getShopCartIds() != null && !orderDTO.getShopCartIds().isEmpty()) {

            ResultBean<List<ShopCartItemVO>> cartResult = shopCartFeignClient.getCheckedShopCartItems();
            if (!cartResult.isSuccess()) {
                throw new RuntimeException("获取购物车信息失败");

            }
            return cartResult.getData();*/
        //购物车路径
        else if (orderDTO.getShopCartIds() != null && !orderDTO.getShopCartIds().isEmpty()) {
            List<ShopCartItemVO> mockCartItems = new ArrayList<>();
            Map<Long, ShopCartItemVO> mockDataMap = new HashMap<>();

            ShopCartItemVO item1 = new ShopCartItemVO();
            item1.setSkuId(101L);
            item1.setSpuId(1001L);
            item1.setCount(1);
            item1.setShopId(1L);
            item1.setSkuPriceFee(5000L); // 50元
            item1.setSpuName("商品1");
            item1.setSkuName("规格1");
            item1.setImgUrl("https://example.com/product1.jpg");
            mockDataMap.put(1L, item1);

            ShopCartItemVO item2 = new ShopCartItemVO();
            item2.setSkuId(102L);
            item2.setSpuId(1002L);
            item2.setCount(2);
            item2.setShopId(1L);
            item2.setSkuPriceFee(3000L); // 30元
            item2.setSpuName("商品2");
            item2.setSkuName("规格2");
            item2.setImgUrl("https://example.com/product2.jpg");
            mockDataMap.put(2L, item2);

            ShopCartItemVO item3 = new ShopCartItemVO();
            item3.setSkuId(103L);
            item3.setSpuId(1003L);
            item3.setCount(3);
            item3.setShopId(2L);
            item3.setSkuPriceFee(2000L); // 20元
            item3.setSpuName("商品3");
            item3.setSkuName("规格3");
            item3.setImgUrl("https://example.com/product3.jpg");
            mockDataMap.put(3L, item3);

            for (Long cartId : orderDTO.getShopCartIds()) {
                if (mockDataMap.containsKey(cartId)) {
                    mockCartItems.add(mockDataMap.get(cartId));
                }
            }
            return mockCartItems;


        } else {
            throw new RuntimeException("订单信息不完整");

        }
    }

    private List<ShopOrderVO> calculateShopOrders(List<ShopCartItemVO> items) {
        //按店铺分组
        Map<Long, List<ShopCartItemVO>> shopItemsMap = items.stream().collect(Collectors.groupingBy(ShopCartItemVO::getShopId));

        return shopItemsMap.entrySet().stream().map(entry -> {
            ShopOrderVO shopOrder = new ShopOrderVO();
            shopOrder.setShopId(entry.getKey());
            //设置商品列表
            List<OrderItemVO> orderItems = entry.getValue().stream().map(item -> {
                OrderItemVO orderItem = new OrderItemVO();
                orderItem.setSpuId(item.getSpuId());
                orderItem.setSkuId(item.getSkuId());
                orderItem.setSpuName(item.getSpuName());
                orderItem.setSkuName(item.getSkuName());
                orderItem.setPic(item.getImgUrl());
                orderItem.setCount(item.getCount());
                orderItem.setPrice(item.getSkuPriceFee());
                orderItem.setTotalAmount(item.getSkuPriceFee() * item.getCount());
                return orderItem;
            }).collect(Collectors.toList());
            shopOrder.setOrderItems(orderItems);
            //计算店铺订单总金额
            long shopTotal = orderItems.stream().mapToLong(OrderItemVO::getTotalAmount).sum();
            shopOrder.setTotalAmount(shopTotal);
            //计算运费（简化出路，一律十元）
            shopOrder.setFreight(1000L);
            return shopOrder;
        }).collect(Collectors.toList());
    }

    @Transactional
    @Override
    public String submitOrder(Long userId) {
        //检查缓存中的订单信息
        OrderConfirmVO confirmVO = orderRedisUtil.getOrderConfirm(userId, OrderConfirmVO.class);
        if (confirmVO == null) {
           throw new RuntimeException("订单信息已过期，请重新下单");
        }
        //2.防止重复提交
        if (!orderRedisUtil.tryLockSubmit(userId)) {
           throw new RuntimeException("订单已提交，请勿重复提交");
        }
        try {
            // 3. 创建主订单（所有数据从confirmVO获取）
            Order order = new Order();
            order.setOrderId("SCDD" + snowflakeIdWorker.nextId());
            order.setUserId(userId);
            order.setDeliveryType(confirmVO.getDeliveryType()); // 从缓存取
            order.setPaymentTypes(confirmVO.getPaymentType());  // 从缓存取
            order.setRemarks(confirmVO.getRemarks());           // 需确认VO中有此字段
            order.setStatus(1); // 待支付状态
            order.setTotal(confirmVO.getTotalAmount());
            order.setAllCount(confirmVO.getTotalCount());
            order.setOrderAddrId(confirmVO.getUserAddr().getAddrId());

            orderMapper.insert(order);
            //4.保存订单项
            List<OrderItem> orderItems = confirmVO.getShopOrders().stream()
                    .flatMap(shopOrder -> shopOrder.getOrderItems().stream()
                            .map(item -> {
                                OrderItem orderItem = new OrderItem();
                                orderItem.setOrderId(order.getOrderId());
                                orderItem.setUserId(order.getUserId()); // 设置用户id数据库如果关联可以省略
                                orderItem.setShopId(shopOrder.getShopId());
                                orderItem.setSpuId(item.getSpuId());
                                orderItem.setSkuId(item.getSkuId());
                                orderItem.setSpuName(item.getSpuName());
                                orderItem.setSkuName(item.getSkuName());
                                orderItem.setPic(item.getPic());
                                orderItem.setCount(item.getCount());
                                orderItem.setPrice(item.getPrice());
                                orderItem.setSpuTotalAmount(item.getTotalAmount());
                                return orderItem;
                            }))
                    .collect(Collectors.toList());
            orderItemService.saveBatch(orderItems);
            //5.如果是购物车下单，清除购物车
            if (confirmVO.getShopCartIds() != null && !confirmVO.getShopCartIds().isEmpty()) {
                // 模拟Feign调用返回成功
                log.info("模拟清空购物车成功，删除的购物车项ID: {}", confirmVO.getShopCartIds());
                ResultBean<Void> deleteResult = ResultBean.success(null);
             /*   ResultBean<Void> deleteResult = shopCartFeignClient.deleteItem(orderDTO.getShopCartIds());*/
                if (!deleteResult.isSuccess()) {
                    log.warn("清除购物车失败: {}", deleteResult.getMsg());
                }
            }
            //6.清楚缓存
            orderRedisUtil.deleteOrderConfirm(userId);
            return order.getOrderId();
        } finally {
            orderRedisUtil.unlockSubmit(userId);
        }
    }


    /**
     * 生成订单ID(线程安全)
     * 这个方法被放弃了但是先保留着，以后有需要再说吧
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW) // 使用新事务，避免大事务问题
    public synchronized String generateOrderId() {
        //获取系统日期     // 获取系统年月 (格式: yyyyMM)
        String ym= DateUtils.getSystemTimeYM();
        //1. 判断 当前内存中是否有最大编码  // 1. 查询数据库获取当前最大订单号
        String currentMaxCode = orderMapper.queryMaxCode();
        // 2. 如果当月没有订单，则生成第一个订单号
        if (currentMaxCode == null || !currentMaxCode.startsWith("SCDD" + ym)) {
            return "SCDD" + ym + "0001";
        }

        // 3. 提取序列号部分并递增
        String seqStr = currentMaxCode.substring(8); // 获取后4位序列号
        int sequence = Integer.parseInt(seqStr);
        if (sequence >= 9999) {
            throw new RuntimeException("当月订单号已用完");
        }

        // 4. 生成新订单号
        return String.format("SCDD%s%04d", ym, sequence + 1);


    }
}
